package com.lhq.plugin.toolkit;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;

/**
 * @author 钱多多--李海青
 *
 */
public class HttpClientToolkit {

    private static final int DEFAULT_CONNECT_TIMEOUT = 2000;
    private static final int DEFAULT_READ_TIMEOUT = 5000;
    
    private static final RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)
            .setSocketTimeout(DEFAULT_READ_TIMEOUT)
            .setCookieSpec(CookieSpecs.STANDARD)
            .build();
    private static volatile CloseableHttpClient httpClient = null;

    private HttpClientToolkit() {
    }

    public static String doGet(String uri, Map<String, String> params) throws Exception {
        httpClient = sslClient();
        URIBuilder builder = new URIBuilder(uri);
        if (params != null && !params.isEmpty()) {
            for (Entry<String, String> entry : params.entrySet()) {
                builder.setParameter(entry.getKey(), entry.getValue());
            }
        }
        HttpGet httpGet = new HttpGet(builder.build());
        httpGet.setConfig(requestConfig);
        return httpClient.execute(httpGet, new BasicResponseHandler());
    }


    /**
     * 创建支持ssl的客户端
     * 
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    private static CloseableHttpClient sslClient() throws NoSuchAlgorithmException, KeyManagementException {
        if (httpClient == null) {
            synchronized (HttpClientToolkit.class) {
                if (httpClient == null) {
                    X509TrustManager trustManager = new X509TrustManager() {
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }

                        @Override
                        public void checkClientTrusted(X509Certificate[] xcs, String str) {
                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] xcs, String str) {
                        }
                    };
                    SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
                    ctx.init(null, new TrustManager[] { trustManager }, null);
                    SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);

                    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.INSTANCE)
                            .register("https", socketFactory)
                            .build();

                    // 创建ConnectionManager，添加Connection配置信息
                    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, null, null, null, -1, TimeUnit.MILLISECONDS);
                    connectionManager.setMaxTotal(200);
                    connectionManager.setDefaultMaxPerRoute(50);
                    connectionManager.setValidateAfterInactivity(2000);

                    // 创建httpClient对象
                    httpClient = HttpClients.custom()
                            .setConnectionManager(connectionManager)
                            .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() {
                                @Override
                                public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                                    long keepAlive = super.getKeepAliveDuration(response, context);
                                    return keepAlive > 0 ? keepAlive : 55000;
                                }
                            })
                            .setRetryHandler(new HttpRequestRetryHandler() {
                                @Override
                                public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                                    if (exception instanceof NoHttpResponseException && executionCount < 3) {
                                        return true;
                                    }
                                    return false;
                                }
                            })
                            .setDefaultRequestConfig(requestConfig)
                            .build();
                }
            }
        }
        return httpClient;
    }


}
